package top.infopub.mgc.core.service.impl;


import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import top.infopub.generic.GenericDao;
import top.infopub.generic.GenericServiceImpl;
import top.infopub.mgc.core.dao.MsgTemplateDao;
import top.infopub.mgc.core.domain.SysOperatorDomain;
import top.infopub.mgc.core.domain.TemplateInfo;
import top.infopub.mgc.core.service.MsgTemplateService;
import top.infopub.model.mgc.MsgTemplate;
import top.infopub.zookeeper.confclient.listener.ConfigurationListener;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;


@Service("msgTemplateService")
public class MsgTemplateServiceImpl extends GenericServiceImpl<MsgTemplate, String> implements MsgTemplateService, ConfigurationListener {

    private static Logger logger = LoggerFactory.getLogger(MsgTemplateServiceImpl.class);

    @Autowired
    private MsgTemplateDao msgTemplateDao;

    private Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);

    private Map<String, TemplateInfo> map_id_template = null;

    private Map<String, HashSet<TemplateInfo>> map_maincode_templates = null;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    @Override
    public GenericDao<MsgTemplate, String> getDao() {
        return msgTemplateDao;
    }

    @Override
    public List<SysOperatorDomain> selectUsersByPurCode(String purCode) {
        if (StringUtils.isEmpty(purCode)) {
            return null;
        }
        return msgTemplateDao.selectUsersByPurCode(purCode);
    }

    @PostConstruct
    public void loadTemplateInfo() {
        cfg.setDefaultEncoding("UTF-8");
        List<TemplateInfo> tinfos = msgTemplateDao.selectTemplateInfos();
        if (tinfos != null) {
            try {
                lock.writeLock().lock();
                StringTemplateLoader stringLoader = new StringTemplateLoader();
                map_id_template = new HashMap<String, TemplateInfo>();
                map_maincode_templates = new HashMap<String, HashSet<TemplateInfo>>();
                for (TemplateInfo tinfo : tinfos) {
                    try {
                        map_id_template.put(tinfo.getId().toString(), tinfo);
                        HashSet<TemplateInfo> _tinfos = map_maincode_templates.get(tinfo.getTempMainCode());
                        if (_tinfos == null) {
                            _tinfos = new HashSet<TemplateInfo>();
                            map_maincode_templates.put(tinfo.getTempMainCode(), _tinfos);
                        }
                        if (!StringUtils.isEmpty(tinfo.getTemplateContent())) {
                            stringLoader.putTemplate(tinfo.getId(), tinfo.getTemplateContent());
                        }
                        _tinfos.add(tinfo);
                    }
                    catch (Exception e) {
                        logger.error("generate Freemarker Template, id: " + tinfo.getId(), e);
                    }
                }
                cfg.setTemplateLoader(stringLoader);
                genFreemarkerTemplate();
            }
            finally {
                lock.writeLock().unlock();
            }
        }
    }

    @Override
    public TemplateInfo selectTemplateInfoById(String id) {
        try {
            lock.readLock().lock();
            return map_id_template.get(id);
        }
        catch (Exception e) {
            return null;
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public HashSet<TemplateInfo> selectTemplatesByMainCode(String mainCode) {
        try {
            lock.readLock().lock();
            return map_maincode_templates.get(mainCode);
        }
        catch (Exception e) {
            return null;
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public void configurationChangedNotice(String keyName, String value) {
        if (ZK_NAME.equalsIgnoreCase(keyName)) {
            loadTemplateInfo();
        }
    }

    /**
     * 循环遍历，生成freemarkerTemplate对象
     */
    private void genFreemarkerTemplate() {
        for (Entry<String, HashSet<TemplateInfo>> map_maincode_temp : map_maincode_templates.entrySet()) {
            HashSet<TemplateInfo> _sets = map_maincode_temp.getValue();
            if (_sets != null) {
                for (TemplateInfo _set : _sets) {
                    try {
                        _set.setTemplateObj(cfg.getTemplate(_set.getId()));
                    }
                    catch (Exception e) {
                        logger.error("generate Freemarker Template, id: " + _set.getId(), e);
                    }
                }
            }
        }
        for (Entry<String, TemplateInfo> map_id_t : map_id_template.entrySet()) {
            try {
                map_id_t.getValue().setTemplateObj(cfg.getTemplate(map_id_t.getValue().getId()));
            }
            catch (Exception e) {
                logger.error("generate Freemarker Template, id: " + map_id_t.getValue().getId(), e);
            }
        }
    }
    
}